package Util;

public class HashTable 
{
	private static final int SIZE = 4096;
	private Object[] _hashTable;

	/**
	 * Default constructor.
	 */
	public HashTable() 
	{ 
		this._hashTable = new Object[HashTable.SIZE]; 
	}

	/**
	 * Puts a new key-value pair into the hash table.
	 * @param key the key string.
	 * @param obj the value object.
	 */
	public void put(Object key, Object obj) 
	{ 
		this._hashTable[ hashFunction(key) ] = obj; 
	}

	/**
	 * Gets a object from the hash table.
	 * @param key the value used to obtain the desired index.
	 * @return
	 * The object found for the provided key.
	 */
	public Object getValue(Object key) 
	{ 
		return (_hashTable[ hashFunction(key) ]); 
	}
	
	/**
	 * Gets all the objects into the hash table.
	 * @return
	 * An array with all the objects found.
	 */
	public Object[] getAll()
	{
		Object[] obj = new Object[1];
		for (int i = 0; i < _hashTable.length; i++)
		{
			if (_hashTable[i] != null)
			{
				obj[obj.length-1] = _hashTable[i];
				Object[] temp = new Object[obj.length+1];
				System.arraycopy(obj, 0, temp, 0, obj.length);
				obj = temp;
			}		
		}
		Object[] temp = new Object[obj.length-1];
		System.arraycopy(obj, 0, temp, 0, obj.length-1);
			
		return temp;
	}
	
	/**
	 * Gets the Object and then removes from the table
	 * @param key
	 */
	public Object getValueAndRemove (Object key)
	{
		Object obj = _hashTable[ hashFunction(key) ];
		_hashTable[ hashFunction(key) ] = null;
		return obj;
		
	}

	/**
	 * Calculates a hash based on the key.
	 * @param key the key string for the hash calculation.
	 * @return
	 * An integer value with the result of the hash calculation.
	 */
	private int hashFunction (Object key) 
	{ 
		return ( module(key.hashCode() * key.hashCode() + key.toString().length() * key.hashCode()) ) % HashTable.SIZE;
	}

	/**
	 * Calculates the module of a number.
	 * @param num the number to be used in the calculation.
	 * @return
	 * The module of the number received as a parameter.
	 */
	private int module(int num) 
	{ 
		return (num < 0) ? -num : num; 	
	}
}